%{
#define YYERROR_VERBOSE
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "nodesconf.h"

extern FILE *nodesconfin;

void yyerror(struct nodesconf* conf, char *s)
{
    printf("%s\n", s);
}

nodesconf(struct nodesconf* conf)
{
    FILE *cfgfile = fopen("./nodes.conf", "r");
    if (cfgfile) {
        nodesconfin = cfgfile;
        yyparse(conf);
        fclose(cfgfile);
    } else {
        printf("error open file %s\n", "./nodes.conf");
    }
}
%}

%parse-param {struct nodesconf* conf};

%union
{
    char*			str;
    struct nodetable*		tab;
    struct nodename*		nod;
    struct nodesection*		nodesec;
    struct group*		groupsec;
    struct nodesconf*		conf;
}

%token GROUP_BEGIN NODE_BEGIN GROUP BEGIN_DEFS END_DEFS END TABLE CONDI ALIAS UNDERSCORE EQUAL QUOTE RECEIVER_NUMBER RECEIVER_NAME SENDER_NUMBER SENDER_NAME
%token <str> NAME DEF
%type <str> DEFS
%type <tab> TABLE_DEF
%type <nod> NODES
%type <nodesec> NODE_SECTION
%type <groupsec> GROUP_LIST
%type <conf> CONFIG

%start CONFIG

%%
CONFIG: GROUP_BEGIN GROUP_LIST END NODE_SECTION {
    $$ = conf;
    $$->groupsection=$2;
    $$->nodessection=$4;
};
GROUP_LIST: GROUP NAME EQUAL QUOTE NODES QUOTE {
    $$ = malloc(sizeof(struct group));
    $$->name=$2;
    $$->nodes=$5;
    $$->next=NULL;
} | GROUP NAME EQUAL QUOTE NODES QUOTE GROUP_LIST {
    $$ = malloc(sizeof(struct group));
    $$->name=$2;
    $$->nodes=$5;
    $$->next=$7;
};
NODE_SECTION: NODE_BEGIN NODES TABLE_DEF END {
    $$ = malloc(sizeof(struct nodesection));
    $$->nodes=$2;
    $$->tables=$3;
    $$->next=NULL;
} | NODE_BEGIN NODES TABLE_DEF END NODE_SECTION {
    $$ = malloc(sizeof(struct nodesection));
    $$->nodes=$2;
    $$->tables=$3;
    $$->next=$5;
};
NODES: NAME {
    $$ = malloc(sizeof(struct nodename));
    $$->name=$1;
    $$->next=NULL;
} | NAME NODES {
    $$ = malloc(sizeof(struct nodename));
    $$->name=$1;
    $$->next=$2;
};
TABLE_DEF: TABLE NAME EQUAL QUOTE DEFS QUOTE {
    $$ = malloc(sizeof(struct nodetable));
    $$->name=$2;
    $$->fields=$5;
    $$->condi="";
    $$->alias=$2;
    $$->next=NULL;
} | CONDI NAME EQUAL QUOTE DEFS QUOTE {
    $$ = malloc(sizeof(struct nodetable));
    $$->name=$2;
    $$->fields="*";
    $$->condi=$5;
    $$->alias=$2;
    $$->next=NULL;
} | ALIAS NAME EQUAL QUOTE NAME QUOTE {
    $$ = malloc(sizeof(struct nodetable));
    $$->name=$2;
    $$->fields="*";
    $$->condi="";
    $$->alias=$5;
    $$->next=NULL;
} | TABLE NAME EQUAL QUOTE DEFS QUOTE TABLE_DEF {
    struct nodetable* nexttable = $7;
    while (1) {
        if (nexttable==NULL) {
            $$ = malloc(sizeof(struct nodetable));
            $$->name=$2;
            $$->fields=$5;
            $$->condi="";
            $$->alias=$2;
            $$->next=$7;
            break;
        } else if (strcmp($2, nexttable->name)==0) {
            $$ = $7;
            $$->fields=$5;
            break;
        } else {
            nexttable = nexttable->next;
        }
    }
} | CONDI NAME EQUAL QUOTE DEFS QUOTE TABLE_DEF {
    struct nodetable* nexttable = $7;
    while (1) {
        if (nexttable==NULL) {
            $$ = malloc(sizeof(struct nodetable));
            $$->name=$2;
            $$->fields="*";
            $$->condi=$5;
            $$->alias=$2;
            $$->next=$7;
            break;
        } else if (strcmp($2, nexttable->name)==0) {
            $$ = $7;
            $$->condi=$5;
            break;

        } else {
            nexttable = nexttable->next;
        }
    }
} | ALIAS NAME EQUAL QUOTE NAME QUOTE TABLE_DEF {
    struct nodetable* nexttable = $7;
    while (1) {
        if (nexttable==NULL) {
            $$ = malloc(sizeof(struct nodetable));
            $$->name=$2;
            $$->fields="*";
            $$->condi="";
            $$->alias=$5;
            $$->next=$7;
            break;
        } else if (strcmp($2, nexttable->name)==0) {
            $$ = $7;
            $$->alias=$5;
            break;
        } else {
            nexttable = nexttable->next;
        }
    }
};
DEFS: DEF {
    $$ = calloc(sizeof(char), 600);
    $$[0] = '\0';
    strcat($$, $1);
} | RECEIVER_NUMBER {
    $$ = calloc(sizeof(char), 600);
    $$[0] = '\0';
    strcat($$, "1");
} | RECEIVER_NAME {
    $$ = calloc(sizeof(char), 600);
    $$[0] = '\0';
    strcat($$, "2");
} | SENDER_NUMBER {
    $$ = calloc(sizeof(char), 600);
    $$[0] = '\0';
    strcat($$, "azs1");
} | SENDER_NAME {
    $$ = calloc(sizeof(char), 600);
    $$[0] = '\0';
    strcat($$, "azs2");
} | DEFS DEF{
    $$ = $1;
    strcat($$, $2);
} | DEFS RECEIVER_NUMBER {
    $$ = $1;
    strcat($$, "1");
} | DEFS RECEIVER_NAME {
    $$ = $1;
    strcat($$, "azs2");
} | DEFS SENDER_NUMBER {
    $$ = $1;
    strcat($$, "2");
} | DEFS SENDER_NAME {
    $$ = $1;
    strcat($$, "azs2");
};
%%
